/*
Copyright DTCC 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

Unless required by ctrslicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';
var ctrs = angular.module("app.controllers", ['app.services']);
/*-----------------------------Controllers for HTML div elements------------------------------------ */

ctrs.factory("ledgerData", function($rootScope) {
	console.log("inside legerData");
    Chart.defaults.global.defaultFontColor = '#fff';
    var ledger = {};
    ledger.stat = {}
    var rc = $rootScope;
    var locked = false;
    var newData = null;
    window.lock = function() {
        locked = true;
        //console.log('locked');
    }
    window.redraw = function() {
        //console.log('redraw',newData);
        //console.log('unlocking');
        if (newData) {
            statsData = newData;
            rc.$broadcast("stats_broadcast_upd");
        }
        locked = false;
        newData = false;
    }
    // window.addEventListener("load", function() {
        var socket = io('http://' + window.location.host);
        socket.on('stats', function(msg) {
            ledger.stat = JSON.parse(msg);
            rc.$broadcast("stats_broadcast_upd");
        });
        socket.on('update', function(msg) {
            var data = JSON.parse(msg);
            if (data.chain) {
                ledger.chain = data.chain;
                ledger.chain.cssClass = 'fade';
            }
            if (data.peers) {
                for (var i = 0; i < data.peers.length; i++) {
                    data.peers[i].cssClass = 'fade';
                }
                ledger.peers = data.peers;
            }
            if (data.blocks) {
                for (var i = 0; i < data.blocks.length; i++) {
                    data.blocks[i].cssClass = 'fade';
                    for (var j = 0; data.blocks[i].transactions
                        && j < data.blocks[i].transactions.length; j++) {
                        data.blocks[i].transactions[j].cssClass = 'fade';
                    }
                }
                ledger.blocks = data.blocks;
            }
            rc.$broadcast("handle_broadcast_upd");
        });
    // })
    return ledger;
})
ctrs.controller("BLOCKS", ['$scope', 'ledgerData', '$timeout',
    function($scope, ledgerData, $timeout) {
        // Used to update which block or transaction information should display once user chooses view or expand button from table
        $scope.selected = 0;
        $scope.initial = 0;
        $scope.info = [];
        $scope.infoc = {};

        $scope.loader = {
            loading: true,
        };
        $scope.hideloader = function() {
            $scope.loader.loading = false;
        }

        $scope.update = function(height) {
                if (ledgerData.blocks.length > 11)
                    $scope.number_of_blocks_to_display = 11;
                else
                    $scope.number_of_blocks_to_display = height;

                var index = 0; // number of responses returned from server
                $scope.info2 = [];
                $scope.trans2 = [];
                for (var i = ledgerData.blocks.length; i >= 0; --i) {
                    var block = ledgerData.blocks[i];
                    // if (!block || !block.nonHashData)
                    if (!block)
                        continue;
                    // var date = new Date(null);
                    // date.setSeconds(block.nonHashData.localLedgerCommitTimestamp.seconds);
                    // date.toISOString().substr(11, 8);
                    // block.nonHashData.localLedgerCommitTimestamp.date = date;
                    block.location = index;
                    $scope.info2[index] = block;
                    if (block.transactions && block.transactions.length) {
                        for (var k = 0; k < block.transactions.length; k++) {
                            var date2 = new Date(null);
                            date2.setSeconds(block.transactions[k].timestamp.seconds);
                            block.transactions[k].date = date2;
                            block.transactions[k].origin = block.blockNum;
                            $scope.trans2.push(block.transactions[k]);
                        }
                    }
                    index++;
                    // once all 10 GET requests are recieved and correctly stored inorder in array, we turn off loading symbol, and proceed to get all transactions from recieved blocks
                    if (index == $scope.number_of_blocks_to_display || i == 0) {
                        $scope.hideloader();
                        $scope.trans = [];
                        for (var k = 0; k < $scope.trans2.length; k++) {
                            $scope.trans = $scope.trans.concat($scope.trans2[k]);
                        }
                        // after all the block information is ready, $scope.range is initialized which is used in ng-repeat to itterate through all blocks, initialzed now to maintain smooth animation
                        $scope.range = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
                        $timeout(function() {
                            $scope.info = $scope.info2;
                        }, 40);
                    }
                }
            }
            // broadcast reciever get chain information from CURRENT controller that initially calls http request, once height is known, specific blocks begin to be retrieved in $scope.update()
        $scope.$on("handle_broadcast_upd", function() {
            $scope.size = ledgerData.chain.height;
            $scope.update($scope.size - 1);
        });
        // updates selected block number and displays form with transaction info based on selection
        $scope.Update_selected_block = function(idx) {
            //$scope.selected = x;
            $scope.infoc = angular.copy($scope.info[idx]);
            $scope.infoc.blockNum = $scope.size - idx - 1;
            document.forms["change2"].submit();
        }
    }
]);

ctrs.controller("CURRENT", ['$scope', '$timeout', 'ledgerData',
    function($scope, $timeout, ledgerData) {
		console.log(ledgerData);
        $scope.info = ledgerData.chain;
        $scope.$on("handle_broadcast_upd", function() {
            $scope.info = ledgerData.chain;
        });
    }
]);

ctrs.controller("NETWORK", ['$scope', 'ledgerData', function($scope, ledgerData) {
    $scope.$on("handle_broadcast_upd", function() {
        $scope.peers = ledgerData.peers;
        $scope.$apply();
    });
}]);
/** 
 * Control to show block generation animation
 */
ctrs.controller('bcBlocks', ['$scope', 'ledgerData', function($scope, ledgerData) {
    const LOW_WATERMARK_BLOCK = 20; // TODO: pass this value from HTML?
    const MAX_BLOCK = 30; // TODO: pass this value from HTML?
    var localblocks = new Array(),
        preHeight = 0;
    $scope.$on("handle_broadcast_upd", function() {
        if (ledgerData.chain.height > preHeight) {
            addNewBlock(ledgerData.chain.height);
            preHeight = ledgerData.chain.height;
            $scope.$apply();
        }
    });

    $scope.select = function(index) {
        var blockNum = localblocks[index];
        $scope.infoc = ledgerData.blocks.filter(function(item) {
            return item.blockNum == blockNum;
        })[0];
        document.forms["select-block"].submit();
    };

    var addNewBlock = function(height) {
        var start = preHeight === 0 ? Math.max(0, height - LOW_WATERMARK_BLOCK + 1) :
            localblocks[localblocks.length - 1] + 1;
        for (var i = start; i < height; i++) {
            localblocks.push(i);
        }
        preHeight = height;
        if (localblocks.length > MAX_BLOCK) {
            // TODO: fade-out animation
            localblocks.splice(0, localblocks.length - LOW_WATERMARK_BLOCK);
        }
        $scope.blocks = localblocks;
    };
}]);
/**
 * End of animation
 */
ctrs.controller("GRAPH", ['$scope', 'ledgerData', function($scope, ledgerData) {
    $scope.$on("stats_broadcast_upd", function() {
        var statsData = ledgerData.stat;
        $scope.checkTime = statsData.checkTime;
        if ($scope.avgTxnLatency < statsData.avgTxnLatency)
            $scope.avgTxnLatencySc = 1;
        else if ($scope.avgTxnLatency > statsData.avgTxnLatency)
            $scope.avgTxnLatencySc = -1;
        else
            $scope.avgTxnLatencySc = 0;
        $scope.avgTxnLatency = statsData.avgTxnLatency;

        if ($scope.txnRate < statsData.txnRate)
            $scope.txnRateSc = 1;
        else if ($scope.txnRate > statsData.txnRate)
            $scope.txnRateSc = -1;
        else
            $scope.txnRateSc = 0;
        $scope.txnRate = statsData.txnRate;

        if ($scope.mineRate < statsData.mineRate)
            $scope.mineRateSc = 1;
        else if ($scope.mineRate > statsData.mineRate)
            $scope.mineRateSc = -1;
        else
            $scope.mineRateSc = 0;
        $scope.mineRate = statsData.mineRate;
        $scope.$apply();
    });
}]);

ctrs.controller("TX_RATE", ['$scope', 'ledgerData', function($scope, ledgerData) {
    var sampleLables = ["20:06:12", "20:06:42", "20:07:12", "20:07:42", "20:08:12", "20:08:42", "20:09:03", "20:09:33"];
    var sampleData = [0, 0, 0, 0, 0, 0, 0, 0];
    var dataChg = true;
    $scope.$on("stats_broadcast_upd", function() {
        var statsData = ledgerData.stat;
        if ($scope.chart.data && statsData.txRateGraph) {
            $scope.chart.data.datasets[0].data = statsData.txRateGraph.txRate;
            $scope.chart.data.labels = statsData.txRateGraph.time;
            $scope.chart.update();
        }
    });
    var data = {
        labels: sampleLables,
        datasets: [{
            label: "Transaction Rate by time",
            fill: false,
            lineTension: 0.1,
            backgroundColor: "rgba(75,192,192,1)",
            borderColor: "rgba(75,192,192,1)",
            borderCapStyle: 'butt',
            borderDash: [],
            borderDashOffset: 0.0,
            borderJoinStyle: 'miter',
            pointBorderColor: "rgba(75,192,192,1)",
            pointBackgroundColor: "#fff",
            pointBorderWidth: 1,
            pointHoverRadius: 5,
            pointHoverBackgroundColor: "rgba(75,192,192,1)",
            pointHoverBorderColor: "rgba(220,220,220,1)",
            pointHoverBorderWidth: 2,
            pointRadius: 1,
            pointHitRadius: 10,
            data: sampleData,
            spanGaps: false,
        }]
    };

    $scope.ctx = $("#tx_rate");
    $scope.chart = new Chart($scope.ctx, {
        type: 'line',
        data: data,
        options: {
            animation: false,
            scales: {
                yAxes: [{
                    scaleLabel: {
                        display: true,
                        labelString: 'Rate',
                        fontColor: '#fff',
                        ticks: 1
                    },
                    ticks: {
                        min: 0,
                        stepSize: 1,
                    }
                }],

                xAxes: [{
                    scaleLabel: {
                        display: true,
                        labelString: 'Time(HH:MM:SS)',
                    },
                    ticks: {
                        min: 0,
                        stepSize: 1,
                    }
                }],
            }
        }
    });
}]);

ctrs.controller("BLK_RATE", ['$scope', 'ledgerData', function($scope, ledgerData) {
    var data;
    $scope.$on("stats_broadcast_upd", function() {
        var statsData = ledgerData.stat;
        if (!data) {
            data = {
                labels: statsData.blkRateGraph.time,
                datasets: [{
                    label: "Block Rate by time",
                    fill: false,
                    lineTension: 0.1,
                    backgroundColor: "yellow", //fille color top icon
                    borderColor: "yellow", //line color
                    borderCapStyle: 'butt',
                    borderDash: [],
                    borderDashOffset: 0.0,
                    borderJoinStyle: 'miter',
                    pointBorderColor: "yellow",
                    pointBackgroundColor: "yellow",
                    pointBorderWidth: 1,
                    pointHoverRadius: 5,
                    pointHoverBackgroundColor: "orange",
                    pointHoverBorderColor: "rgba(220,220,220,1)",
                    scaleFontColor: "white",
                    pointHoverBorderWidth: 2,
                    pointRadius: 1,
                    pointHitRadius: 10,
                    spanGaps: false
                }]
            };
            $scope.chart = new Chart($("#blk_rate"), {
                type: 'line',
                data: data,
                options: {
                    animation: false,
                    scales: {
                        yAxes: [{
                            scaleLabel: {
                                display: true,
                                labelString: 'Rate',
                                ticks: 1
                            },
                            ticks: {
                                min: 0,
                                stepSize: 1,
                            }
                        }],
                        xAxes: [{
                            scaleLabel: {
                                display: true,
                                labelString: 'Time(HH:MM:SS)'
                            },
                            ticks: {
                                min: 0,
                                stepSize: 1,
                            }
                        }],
                    }
                }
            });
        } else if (statsData.blkRateGraph) {
            $scope.chart.data.datasets[0].data = statsData.blkRateGraph.blkRate;
            $scope.chart.data.labels = statsData.blkRateGraph.time;
            $scope.chart.update();
        }
    });
}]);

ctrs.controller("TRIGGER",
    function($scope) {
        // collapse and expand navigation menu in mobile/smaller resolution view
        $scope.activate = function() {
            x = document.getElementById("navigation").style.display;
            if (x == "none") {
                document.getElementById("navigation").style.display = "block";
            } else {
                document.getElementById("navigation").style.display = "none";
            }
        }
    }
)

ctrs.controller("TRANSACTIONS", ['$scope', 'ledgerData', function($scope, ledgerData) {
    // controls number of rows to display in the table, initially set to 10
    $scope.row_amount2 = 10;
    /* used to display form with extra transaction information, onclick, transaction_selected is set to the $index of the table row, the displayed form knows
    which transaction information to display getElementById looking at this number*/
    $scope.transaction_selected = 0;
    // loading icon, is displayed while data is loading
    $scope.loader = {
        loading: true,
    };
    $scope.hideloader = function() {
        $scope.loader.loading = false;
    }

    // handle recieving information from the BLOCKS controller that initally calls the http requests
    $scope.$on("handle_broadcast_upd", function() {
        var latestTrans = [];
        for (var i = ledgerData.blocks.length - 1; i >= 0; --i) {
            var block = ledgerData.blocks[i];
            if (block.transactions && block.transactions.length) {
                for (var k = 0; k < block.transactions.length; k++) {
                    var date2 = new Date(null);
                    date2.setSeconds(block.transactions[k].timestamp.seconds);
                    block.transactions[k].date = date2;
                    block.transactions[k].origin = block.blockNum;
                    latestTrans.push(block.transactions[k]);
                }
            }
            if (latestTrans.length >= $scope.row_amount2) break;
        }
        $scope.trans = latestTrans;
        $scope.hideloader();
        $scope.$apply()
    });

    // update seleted2 index and update form with corresponding transaction info
    $scope.Update_transaction_selection_index = function(x) {
        $scope.transs = angular.copy($scope.trans[x]);
        document.forms["change3"].submit();
    }
}]);

// used to keep navigation menu displayed horizontally when resolution change from menu button to navigation bar, runs whenever window resizes
function restore() {
    var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    if (width > 600) {
        document.getElementById("navigation").style.display = "block";
    } else {
        document.getElementById("navigation").style.display = "none";
    }
}
//Global chart config
// Chart.defaults.global.defaultFontColor = '#fff';

function randomColor() {
    return 'rgb(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ')';
}
